#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>

unsigned long iter;
char *cmd_argv[28];

static void print_usage(void)
{
	fprintf(stderr,"Usage: <times> <lps|lpm|lph|lpd|lpw|lpM|lpy> [-o outfile] [-e errfile] cmd arga argb...\n");
}

int main( int argc, char *argv[]) {
	int slave, count, argstart = 3;
	unsigned long times;
	int status;
	time_t start;
	time_t interval;
	FILE *outfile = NULL, *errfile = NULL;

	while (argstart < argc) {
		if (!strcmp(argv[argstart], "-o")) {
			argstart++;
			if (argstart == argc ) {
				print_usage();
				fprintf(stderr,"  the output filename is required\n");
				exit(1);
			}
			outfile = fopen(argv[argstart], "w+");
			argstart++;
		} else if (!strcmp(argv[argstart], "-e")) {
			argstart++;
			if (argstart == argc ) {
				print_usage();
				fprintf(stderr,"  the stderr filename is required\n");
				exit(1);
			}
			errfile = fopen(argv[argstart], "w+");
			argstart++;
		} else {
			break;
		}
	}

	if (argstart >= argc) {
		print_usage();
		exit(1);
	}

	if ((times = atoi(argv[1])) < 1) {
		print_usage();
		fprintf(stderr,"  times should be number\n");
		exit(1);
	}

	/* get command  */
	for (count = argstart; count < argc; ++count)
		cmd_argv[count - argstart] = argv[count];

	iter = 0;
	start = time(NULL);
	while (iter < times) {
		if ((slave = fork()) == 0) { /* execute command */
			if (outfile) {
				dup2(fileno(outfile), STDOUT_FILENO);
				//dup2(STDOUT_FILENO, fileno(outfile));
				fclose(outfile);
			}
			if (errfile) {
				dup2(fileno(errfile), STDERR_FILENO);
				//dup2(STDERR_FILENO, fileno(errfile));
				fclose(errfile);
			}
			execvp(cmd_argv[0], cmd_argv);
			exit(99);
		} else if (slave < 0) { /* woops ... */
			fprintf(stderr,"fork failed at iteration %lu\n", iter);
			perror("reason");
			exit(2);
		} else { /* master */
			wait(&status);
		}

		if (status == 99 << 8) {
			fprintf(stderr, "command \"%s\" didn't exec\n", cmd_argv[0]);
			exit(2);
		} else if (status != 0) {
			fprintf(stderr,"bad wait status: 0x%x\n", status);
			exit(2);
		}
		iter++;
		interval = time(NULL) - start;
		if (interval < 2) {
			times++;
		}
	}
#if 0
	fprintf(stdout, "type=%s, cmd=%s, times=%lu, interval=%lu\n", argv[2], argv[3], times, interval);
#endif
	if (!strcmp(argv[2], "lps")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (1.0 * times / interval), argv[2]);
	} else if (!strcmp(argv[2], "lpm")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (60.0 * times / interval), argv[2]);
	} else if (!strcmp(argv[2], "lph")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (60.0 * 60 * times / interval), argv[2]);
	} else if (!strcmp(argv[2], "lpd")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (24.0 * 60 * 60 * times / interval), argv[2]);
	} else if (!strcmp(argv[2], "lpw")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (7 * 24.0 * 60 * 60 * times / interval), argv[2]);
	} else if (!strcmp(argv[2], "lpM")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (30 * 24.0 * 60 * 60 * times / interval), argv[2]);
	} else if (!strcmp(argv[2], "lpy")) {
		fprintf(stderr, "COUNT|%.1f|0|%s\n", (365 * 24.0 * 60 * 60 * times / interval), argv[2]);
	}

	if (outfile) {
		fclose(outfile);
	}
	if (errfile) {
		fclose(errfile);
	}
	return 0;
}
